package com.datasecops.scannerservices.service;

import com.datasecops.scannerservices.util.ByteStreamHelper;
import com.datasecops.scannerservices.util.HttpURLHelper;
import com.datasecops.scannerservices.util.MD5Helper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.jdom2.output.Format;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;

/**
 * Spring容器加载后方法执行,注册服务
 * @author: SunLingzhi
 * @time: 2022/8/9 11:27
 */
@Component
@Order(value = 1)
@Slf4j
public class RegServer implements ApplicationRunner {

    //本机IP
    @Value("${server.address}")
    private String ip;

    //本机Port
    @Value("${server.port}")
    private Integer port;

    //宿主IP
    @Value("${host.address}")
    private String hostIp;

    //宿主Port
    @Value("${host.port}")
    private Integer hostPort;

    //上传的服务器的IP
    @Value("${host.ip}")
    private String ips;



    //该服务唯一主键
    public static String serverId;
    //该服务名称
    public static String serverName;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        serverName = ip + ":" + port;
        serverId = MD5Helper.getGuId(serverName);
        beganRegister();//注册
        configurationFiles();//落盘配置文件
    }

     /**
      * 开始注册
      * @Description
      * @author SunLingzhi
      * @time 2022/8/9 11:30
      * @param
      * @return
      */
    private void beganRegister() {
        if (StringUtils.isBlank(hostIp) || hostPort == null){
            log.error("Failed method beganRegister param is empty hostIp:" + hostIp + " &hostPort:" + hostPort);
            return;
        }
        boolean isSuccess = false;
        String hostServerAddress = "http://"+hostIp+":"+hostPort+"/EE/DlpClientInfoToSrv?Type=RegScannerServerInfo";
        try {
            byte[] paramData = getRegisterParamData();
            if(null == paramData || paramData.length <= 0){
                log.error("Failed method beganRegister paramData is empty hostIp:" + hostIp + " &hostPort:" + hostPort);
                return;
            }
            while (!isSuccess){
                log.info("beganRegister url:" + hostServerAddress);
                String resultData = HttpURLHelper.connection(hostServerAddress,paramData);
                if (null != resultData){
                    isSuccess = true;
                }
                //休眠5s
                Thread.sleep(1000 * 5);
            }
        } catch (Exception e) {
            log.error("Failed method beganRegister error:" + e.getMessage());
        }
        log.info("Service registration succeeded");
    }

     /**
      * 获取注册参数
      * @Description
      * @author SunLingzhi
      * @time 2022/8/9 13:46
      * @param
      * @return
      */
    private byte[] getRegisterParamData() {
        Element infoNode = DocumentHelper.createElement("InfoContent");
        infoNode.addAttribute("ID",serverId);
        infoNode.addAttribute("Name",serverName);
        infoNode.addAttribute("IP",ip);
        infoNode.addAttribute("Port",port+"");
        infoNode.addAttribute("OS","CentOS7");
        infoNode.addAttribute("OSVersion","7.63");

        byte[] paramData = null;
        try {
            String strParamXml = ByteStreamHelper.toXmlString(infoNode);
            paramData = ByteStreamHelper.formatParamDataFlow(strParamXml);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return paramData;
    }


    /**
     *生成服务器通信配置文件
     * @Description
     * @author GeXiaoLong
     * @time 2023/3/8 16:09
     * @param
     * @return
     */
    public void configurationFiles() throws IOException {

        //创建一个Document对象
        Document doc = DocumentHelper.createDocument();
        //创建一个根元素
        Element element = doc.addElement("GlobalConfigration");
        //创建一个子元素
        Element infoDetails = DocumentHelper.createElement("InfoDetails");
        infoDetails.addAttribute("id","");
        infoDetails.addAttribute("RegistryType","NetMonitor");
        element.add(infoDetails);
        //在创建一个子元素
        Element machine = DocumentHelper.createElement("Machine");
        machine.addAttribute("Guid","F2552353-B23A-442B-B4DA-F728809C3E28");
        machine.addAttribute("User","localhost.localdomain");
        machine.addAttribute("Ip","10.26.18.24");
        machine.addAttribute("MAC","3c-ec-ef-a7-46-5d");
        machine.addAttribute("LvlName","none");
        machine.addAttribute("Level","0");
        machine.addAttribute("Status","Registered");
        infoDetails.add(machine);
        //创建一个平级的
        Element server = DocumentHelper.createElement("Server");
        server.addAttribute("User","eedlp");
        server.addAttribute("UserPswd","eedlp");
        server.addAttribute("Ip", ips);
        server.addAttribute("Port","3366");
        server.addAttribute("HttpPort","3311");
        infoDetails.add(server);
        // 创建一个OutputFormat对象，用于指定写入XML文件的格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-16LE");// 设置编码方式
        format.setIndent(true);  // 设置缩进
        format.setNewLineAfterDeclaration(false);  // 不在xml声明后添加换行符
        format.setSuppressDeclaration(false);  // 不省略xml声明
        format.setOmitEncoding(false);  // 不省略编码方式声明

        // 创建一个XMLWriter对象，并指定要写入的文件和输出格式
        //XMLWriter writer = new XMLWriter(new FileOutputStream("/var/n_dlp/GlobalConfig.xml"), format);
        //XMLWriter writer = new XMLWriter(new FileOutputStream("P:\\text\\GlobalConfigs.xml"), format);

        //FileOutputStream fileOutputStream = new FileOutputStream("/var/n_dlp/GlobalConfig.xml");
        FileOutputStream fileOutputStream = new FileOutputStream("P:\\text\\GlobalConfigs.xml");
        fileOutputStream.write(new byte[] { (byte) 0xFF, (byte) 0xFE });//强制写入BOM头
     /*   OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,
                StandardCharsets.UTF_16LE); // 指定编码格式和BOM*/
        XMLWriter writer = new XMLWriter(fileOutputStream, format);

        // 将Document对象写入XML文件
        writer.write(doc);
        //清缓存
        writer.flush();
        // 关闭XMLWriter对象
        writer.close();
    }


    public static void main(String[] args) throws IOException {
        RegServer server = new RegServer();
        server.configurationFiles();
        server.getRegisterParamData();
        //server.beganRegister();
    }


}
